#include "app.h"

uint32_t WS2812_Buffer[24*14];
uint32_t RGB_Data[14];

void WS2812_init(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
	TIM_OCInitTypeDef  TIM_OCInitStructure;
		
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5,ENABLE);  
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); 	
	
	GPIO_PinAFConfig(GPIOA,GPIO_PinSource2,GPIO_AF_TIM5); 
	
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;           
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;       
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;	
	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;     
	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;       
	GPIO_Init(GPIOA,&GPIO_InitStructure);             
	  
	TIM_TimeBaseStructure.TIM_Prescaler = 0;  
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
	TIM_TimeBaseStructure.TIM_Period = 112;   // TIM_Period = 90M/800kHz = 112
	TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1; 	
	TIM_TimeBaseInit(TIM5,&TIM_TimeBaseStructure);

	TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
  TIM_OCInitStructure.TIM_Pulse = 0;
  TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
  TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Reset;
	TIM_OC3Init(TIM5, &TIM_OCInitStructure); 
	TIM_OC3PreloadConfig(TIM5, TIM_OCPreload_Enable); 
	
  TIM_ARRPreloadConfig(TIM5,ENABLE);  
	
	NVIC_InitTypeDef NVIC_InitStructure;  
  DMA_InitTypeDef  DMA_InitStructure;
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1,ENABLE);

	DMA_DeInit(DMA1_Stream0);
  DMA_InitStructure.DMA_Channel = DMA_Channel_6;  
  DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)(&TIM5->CCR3);
  DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)WS2812_Buffer;
  DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;
  DMA_InitStructure.DMA_BufferSize = 0;
  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
  DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word;
  DMA_InitStructure.DMA_MemoryDataSize = DMA_PeripheralDataSize_Word;
  DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
  DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;
  DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;         
  DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
  DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
  DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
  DMA_Init(DMA1_Stream0, &DMA_InitStructure);
		
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);     
  NVIC_InitStructure.NVIC_IRQChannel = DMA1_Stream0_IRQn;     
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 5;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;          
  NVIC_Init(&NVIC_InitStructure);
	
	NVIC_EnableIRQ(DMA1_Stream0_IRQn);
	
	DMA_ITConfig(DMA1_Stream0, DMA_IT_TC, ENABLE);
	DMA_ClearFlag(DMA1_Stream0,DMA_IT_TCIF0);
	
	TIM_DMACmd(TIM5, TIM_DMA_CC3, ENABLE);
	TIM_CtrlPWMOutputs(TIM5, ENABLE);
	TIM_Cmd(TIM5, ENABLE); 
	
//	TIM5->CCR3 = RGB_0;
}

u8 WS2812_SendFlag = 0;

void DMA1_Stream0_IRQHandler(void)
{
	if(DMA_GetFlagStatus(DMA1_Stream0,DMA_FLAG_TCIF0))
	{ 
		TIM5->CCR3 = 0;
		DMA_Cmd(DMA1_Stream0, DISABLE);
		DMA_ClearFlag(DMA1_Stream0,DMA_IT_TCIF0);
		WS2812_SendFlag = 0;
	}
}

void send_Data(uint32_t *rgb,uint16_t len)
{
  uint16_t i,t,c = 0;
	uint8_t r,g,b;

	for(;len>0;len--)
	{
		r = (rgb[c]&0xff0000)>>16;
		g = (rgb[c]&0x00ff00)>>8;
		b = (rgb[c]&0xff);
		c++;
		for(i=0;i<8;i++){
			WS2812_Buffer[i+t] = (0x80&g)>0?RGB_1:RGB_0;g <<= 1;
		}
		for(i=0;i<8;i++){
			WS2812_Buffer[8+i+t] = (0x80&r)>0?RGB_1:RGB_0;r <<= 1;
		}
		for(i=0;i<8;i++){
			WS2812_Buffer[16+i+t] = (0x80&b)>0?RGB_1:RGB_0;b <<= 1;
		}	
    t	+= 24;	
	}
	c = 0;
	
	DMA1_Stream0->NDTR = 336;
	DMA_Cmd(DMA1_Stream0, ENABLE);
}






